﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Portal_Tech;

namespace Portal_Tech
{
    class Distribution
    {
        public static List<SubGroup> Distribute(List<ParadeFloat> parade, List<SubGroup> groups, int numberOfFloats, int startingIndex)
        {
            groups.Sort(delegate(SubGroup g1, SubGroup g2) { return g2.numberInGroup.CompareTo(g1.numberInGroup); });
            int count = groups.Count;
            int median = count / 2 - 1;
            List<SubGroup> added = new List<SubGroup>();
            List<SubGroup> notAdded = new List<SubGroup>();
            int average = 0;
            int sum = 0;
            foreach (SubGroup group in groups)
            {
                sum += group.numberInGroup;
            }
            average = sum / numberOfFloats;

            for (int i = median, j = median + 1; i > 0 && j < count; i--, j++)
            {
                int floatIndex = startingIndex;
                foreach (ParadeFloat pfloat in parade)
                {
                    if (pfloat.numberOfRiders + groups[i].numberInGroup <= average && pfloat.numberOfRiders + groups[i].numberInGroup <= 40)
                    {
                        groups[i].FloatPlacement = pfloat.floatNumber;
                        pfloat.groups.Add(groups[i]);
                        added.Add(groups[i]);
                        pfloat.numberOfRiders += groups[i].numberInGroup;
                        groups[i].SetFrontMiddleBack(floatIndex);
                        break;
                    }
                    floatIndex++;
                }
                floatIndex = startingIndex;
                foreach (ParadeFloat pfloat in parade)
                {
                    if (pfloat.numberOfRiders + groups[j].numberInGroup <= average && pfloat.numberOfRiders + groups[i].numberInGroup <= 40)
                    {
                        groups[j].FloatPlacement = pfloat.floatNumber;
                        pfloat.groups.Add(groups[j]);
                        added.Add(groups[j]);
                        pfloat.numberOfRiders += groups[j].numberInGroup;
                        groups[j].SetFrontMiddleBack(floatIndex);
                        break;
                    }
                    floatIndex++;
                }
            }
            foreach (SubGroup g in groups)
            {
                bool inAdded = false;
                foreach (SubGroup s in added)
                {
                    
                    if (g.GroupID == s.GroupID)
                        inAdded = true;
                }
                if (!inAdded)
                    notAdded.Add(g);
            }
            foreach (SubGroup g in notAdded)
            {
                int floatIndex = startingIndex;
                for (int i = parade.Count - 1; i >= 0; i--)
                {
                    ParadeFloat pfloat = parade[i];
                    if (pfloat.numberOfRiders + g.numberInGroup <= 40)
                    {
                        g.FloatPlacement = pfloat.floatNumber;
                        pfloat.groups.Add(g);
                        added.Add(g);
                        pfloat.numberOfRiders += g.numberInGroup;
                        g.SetFrontMiddleBack(floatIndex);
                        break;
                    }
                    floatIndex++;
                }
            }
            notAdded.Clear();
            foreach (SubGroup g in groups)
            {
                bool inAdded = false;
                foreach (SubGroup s in added)
                {

                    if (g.GroupID == s.GroupID)
                        inAdded = true;
                }
                if (!inAdded)
                    notAdded.Add(g);
            }
           
            return notAdded;
        }

        public static List<SubGroup> FrontToBack(List<SubGroup> groups, List<ParadeFloat> parade)
        {
            List<ParadeFloat> front = new List<ParadeFloat>();
            List<ParadeFloat> back = new List<ParadeFloat>();
            List<SubGroup> frontGroups = new List<SubGroup>();
            List<SubGroup> backGroups = new List<SubGroup>();
            List<SubGroup> middleGroups = new List<SubGroup>();
            List<SubGroup> notAdded = new List<SubGroup>();
            List<ParadeFloat> middleFloat = new List<ParadeFloat>();
            for (int i = 0; i < 7; i++)
            {
                front.Add(parade[i]);
            }
            for (int i = 8; i < 15; i++)
            {
                back.Add(parade[i]);
            }
            middleFloat.Add(parade[7]);
            foreach (SubGroup g in groups)
            {
                if (g.frontMiddleBack > 8)
                {
                    frontGroups.Add(g);
                }
                else if (g.frontMiddleBack < 8)
                {
                    backGroups.Add(g);
                }
                else
                {
                    middleGroups.Add(g);
                }
            }
            notAdded = Distribute(front, frontGroups, 7, 1);
            IEnumerable<SubGroup> temp = notAdded.Union<SubGroup>(Distribute(back, backGroups, 7, 9));
            notAdded = new List<SubGroup>(temp);
            temp =notAdded.Union<SubGroup>(Distribute(middleFloat, middleGroups, 1, 8));
            notAdded = new List<SubGroup>(temp);
            return notAdded;
        }

        public static void distributeOrphans(List<SubGroup> groups, List<ParadeFloat> parade)
        {
            int sum = 0;
            foreach (SubGroup group in groups)
                sum += group.numberInGroup;
            while (sum != 0)
            {
                int min = 40;
                ParadeFloat minFloat = new ParadeFloat();
                foreach (ParadeFloat f in parade)
                {
                    if (f.numberOfRiders < min)
                    {
                        min = f.numberOfRiders;
                        minFloat = f;
                    }
                }
                if (sum > 40 - minFloat.numberOfRiders)
                {
                    sum -= (40 - minFloat.numberOfRiders);
                    minFloat.numberOfRiders += (40 - minFloat.numberOfRiders);
                }
                else
                {
                    minFloat.numberOfRiders += sum;
                    sum -= sum;
                }
            }
        }
    }
}
